import camera from '@ohos.multimedia.camera'
import deviceInfo from '@ohos.deviceInfo'
import image from '@ohos.multimedia.image'
import Logger from '../common/utils/Logger'
import { Context } from '@kit.ArkUI'
/*
 * 相机相关功能
 */

interface profileModel{
  audioBitrate: int,
  audioChannels: int,
  audioCodec: string,
  audioSampleRate: int,
  durationTime: int,
  fileFormat: string,
  videoBitrate: int,
  videoCodec: string,
  videoFrameWidth: int,    //640,
  videoFrameHeight: int,    //480,
  videoFrameRate: int
}

interface locationModel{
  latitude: int
  longitude: int
}

interface videoConfigModel{
  audioSourceType: int
  videoSourceType: int
  profile: profileModel
  url: string
  orientationHint: int
  location: locationModel
  maxSize: int
  maxDuration: int
}

class CameraSizeModel{
  WIDTH: int //640,
  HEIGHT: int  //480
}

const CameraSize:CameraSizeModel = {
  // WIDTH: 1920,
  // HEIGHT: 1080
  WIDTH: 1280, //640,
  HEIGHT: 720  //480
}
export default class CameraService {
  private tag: string = 'CameraService'
  // private context: Context = this.getUIContext().getHostContext() as Context
  private cameraManager: camera.CameraManager|undefined = undefined
  private cameras: Array<camera.CameraDevice> |undefined= undefined
  private cameraInput: camera.CameraInput|undefined = undefined
  private previewOutput: camera.PreviewOutput|undefined = undefined
  private previewShow: camera.PreviewOutput|undefined = undefined
  // private photoOutPut: camera.PhotoOutput = undefined
  private captureSession: camera.Session|undefined = undefined
  private mReceiver: image.ImageReceiver |undefined= undefined
  private videoOutput: camera.VideoOutput|undefined = undefined
  private cameraOutputCapability: camera.CameraOutputCapability|undefined = undefined
  private cameraIndex: number
  private videoConfig: videoConfigModel = {
    audioSourceType: 1,
    videoSourceType: 0,
    profile: {
      audioBitrate: 48000,
      audioChannels: 2,
      audioCodec: 'audio/mp4v-es',
      audioSampleRate: 48000,
      durationTime: 1000,
      fileFormat: 'mp4',
      videoBitrate: 48000,
      videoCodec: 'video/mp4v-es',
      videoFrameWidth: 1280,    //640,
      videoFrameHeight: 720,    //480,
      videoFrameRate: 30
    },
    url: '',
    orientationHint: 0,
    location: {
      latitude: 30,
      longitude: 130
    },
    maxSize: 10000,
    maxDuration: 10000
  }
  private context_: Context;

  constructor(context: Context) {
    let buffer = new ArrayBuffer(1382400);
    this.context = context
    this.mReceiver = image.createImageReceiver(CameraSize.WIDTH, CameraSize.HEIGHT, 2000, 8)
    Logger.info(this.tag, 'createImageReceiver')
    this.mReceiver.on('imageArrival', async () => {
      Logger.info(this.tag, 'imageArrival')
      this.mReceiver.readNextImage((err, image) => {
        Logger.info(this.tag, 'readNextImage')
        if (err || image === undefined) {
          Logger.error(this.tag, 'failed to get valid image')
          return
        }
        image.getComponent(4, async (errMsg, img) => {
          Logger.info(this.tag, 'getComponent')
          if (errMsg || img === undefined) {
            Logger.info(this.tag, 'failed to get valid buffer')
            return
          }

          if (img.byteBuffer) {
            //buffer = img.byteBuffer.slice(0, 460800);
            buffer = img.byteBuffer.slice(0, 1382400);
            Logger.info(this.tag, `video buffer size: ${buffer.byteLength}`);
            const view = new DataView(buffer, 0);
            if (buffer !== undefined) {
              if(this.context_ != undefined){
                this.context_.onFrameCallback(buffer, this.cameraIndex == 1 ? true : false, 21);
              }
            }
          } else {
            Logger.error(this.tag, 'img.byteBuffer is undefined')
          }
          await image.release();
        })
      });

    })
  }

  async inInt(context:Context) {
    Logger.info(this.tag, 'XC inInt')
    this.context_ = context
    Logger.info(this.tag, 'this.context_-----４' +　this.context_)
  }
  async clearInt() {
    Logger.info(this.tag, 'clearInt')
    this.context_ = null
  }

  async initCamera(surfaceId: string, cameraIndex: number) {
    this.cameraIndex = cameraIndex
    Logger.info(this.tag, 'initCamera')
    await this.releaseCamera()
    Logger.info(this.tag, `deviceInfo.deviceType = ${deviceInfo.deviceType}`)
    if (deviceInfo.deviceType === 'default') {
      this.videoConfig.videoSourceType = 1
    } else {
      this.videoConfig.videoSourceType = 0
    }
    // 创建CameraManager对象
    this.cameraManager = await camera.getCameraManager(this.context)
    Logger.info(this.tag, 'getCameraManager')
    // 获取相机列表
    this.cameras = await this.cameraManager.getSupportedCameras()
    Logger.info(this.tag, `get cameras ${this.cameras.length}`)
    if (this.cameras.length === 0) {
      Logger.info(this.tag, 'cannot get cameras')
      return undefined
    }
    let cameraDevice = this.cameras[cameraIndex]
    // 创建相机输入流
    this.cameraInput = await this.cameraManager.createCameraInput(cameraDevice)

    // 打开相机
    this.cameraInput.open()
    Logger.info(this.tag, 'createCameraInput')
    // 获取相机设备支持的输出流能力
    this.cameraOutputCapability = await this.cameraManager.getSupportedOutputCapability(cameraDevice)
    Logger.debug(this.tag, 'cameraOutputCapability: ' + JSON.stringify(this.cameraOutputCapability))
    let previewProfile = this.cameraOutputCapability.previewProfiles[0]
    for (let index = 0; index < this.cameraOutputCapability.previewProfiles.length; index++) {
      Logger.debug(this.tag, 'cameraOutputCap1: ' + this.cameraOutputCapability.previewProfiles[index].format)
      Logger.debug(this.tag, 'cameraOutputCap2: ' + this.cameraOutputCapability.previewProfiles[index].size.height)
      Logger.debug(this.tag, 'cameraOutputCap2: ' + this.cameraOutputCapability.previewProfiles[index].size.width)
    }
    previewProfile.size.height = 720
    previewProfile.size.width = 1280
    // 获取照片显示SurfaceId
    const mSurfaceId = await this.mReceiver.getReceivingSurfaceId()
    // 创建预览输出流,其中参数 surfaceId 参考上文 XComponent 组件，预览流为XComponent组件提供的surface
    Logger.debug(this.tag, 'cameraOutputCap111111: ' + JSON.stringify(previewProfile))
    this.previewShow = await this.cameraManager.createPreviewOutput(previewProfile, mSurfaceId)
    this.previewOutput = await this.cameraManager.createPreviewOutput(previewProfile, surfaceId)
    Logger.info(this.tag, 'createPreviewOutput')
    let photoProfile = this.cameraOutputCapability.photoProfiles[0]
    // 创建拍照输出流
    try {
      // this.photoOutPut = this.cameraManager.createPhotoOutput(photoProfile, mSurfaceId)
    } catch (error) {
      Logger.error(this.tag, `createPhotoOutput failed: ${JSON.stringify(error)}`);
    }
    //创建会话
    this.captureSession = await this.cameraManager.createCaptureSession()
    Logger.info(this.tag, 'createCaptureSession')
    // 开始配置会话
    await this.captureSession.beginConfig()
    Logger.info(this.tag, 'beginConfig')
    // 向会话中添加相机输入流
    await this.captureSession.addInput(this.cameraInput)
    // await this.captureSession.canAddInput
    // 向会话中添加预览输出流
    await this.captureSession.addOutput(this.previewOutput)
    await this.captureSession.addOutput(this.previewShow)
    // 向会话中添加拍照输出流
    // await this.captureSession.addOutput(this.photoOutPut)
    // 提交会话配置
    await this.captureSession.commitConfig()
    // 启动会话
    await this.captureSession.start()
    Logger.info(this.tag, 'captureSession start')
  }

  async onChangeFocusStateChangeStatusFn() {
    this.captureSession.on('focusStateChange', (focusState) => {
      Logger.info(this.tag, `focusStateChange : ${focusState}`)
    })
  }

  //本地相机预览开关
  pausePreview(isPause: boolean) {
    if (isPause) {
      this.previewOutput.stop()
      this.previewShow.stop()
    } else {
      this.previewOutput.start()
      this.previewShow.start()
    }
  }

  //相机释放资源
  async releaseCamera() {
    Logger.info(this.tag, 'releaseCamera')
    if (this.cameraInput) {
      await this.cameraInput.close()
    }
    if (this.previewOutput) {
      await this.previewOutput.release()
    }
    // if (this.photoOutPut) {
    //   await this.photoOutPut.release()
    // }
    if (this.videoOutput) {
      await this.videoOutput.release()
    }
    if (this.captureSession) {
      await this.captureSession.release()
    }
  }
}